package com.changgou.seckill.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSONPath;
import com.changgou.seckill.config.SeckillStatus;
import com.changgou.seckill.dao.SeckillGoodsMapper;
import com.changgou.seckill.dao.SeckillOrderMapper;
import com.changgou.seckill.pojo.SeckillGoods;
import com.changgou.seckill.pojo.SeckillOrder;
import com.changgou.seckill.service.SeckillOrderService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import tk.mybatis.mapper.entity.Example;

import java.time.OffsetDateTime;
import java.util.Date;
import java.util.List;
/****
 * @Author:deng
 * @Description:SeckillOrder业务层接口实现类
 *****/
@Service
public class SeckillOrderServiceImpl implements SeckillOrderService {

    @Autowired
    private SeckillOrderMapper seckillOrderMapper;
    @Autowired
    private SeckillGoodsMapper seckillGoodsMapper;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private RabbitTemplate rabbitTemplate;

    /***
     * 支付失败：删除订单
     * @param username
     */
    @Override
    public void closeOrder(String username) {
        //获取用户排队状态
        String s = stringRedisTemplate.boundValueOps("SeckillStatus_" + username).get();
        SeckillStatus seckillStatus = JSONObject.parseObject(s, SeckillStatus.class);
        //获取商品秒杀时间
        String statusTime = seckillStatus.getTime();
        //获取商品的id
        String goodsId = seckillStatus.getGoodsId();
        //获取订单信息
        Object seckillOrder01 = stringRedisTemplate.boundHashOps("seckillOrder").get(username);
        SeckillOrder seckillOrder = JSONObject.parseObject(seckillOrder01.toString(), SeckillOrder.class);
        //设置支付信息
        seckillOrder.setStatus("2");
        //将支付订单保存到数据库
        seckillOrderMapper.insertSelective(seckillOrder);
        //将redis中的订单数据更新
        stringRedisTemplate.boundHashOps("SeckillOrder").put(username,seckillOrder);

        //获取商品详情
        SeckillGoods seckillGoods = (SeckillGoods)redisTemplate.boundHashOps("SeckillGoods_" + statusTime).get(goodsId);
        if (seckillGoods.getStockCount()<=0){
            //商品已经卖完
            seckillGoods=seckillGoodsMapper.selectByPrimaryKey(seckillGoods.getId());
            seckillGoods.setStockCount(seckillGoods.getStockCount()+1);
            seckillGoodsMapper.updateByPrimaryKeySelective(seckillGoods);
            //更新redis(定时任务)
            //redisTemplate.boundHashOps("SeckillGoods_" + statusTime).put(goodsId,seckillGoods);
        }else {
            //库存进行回滚（队列里，库存总数）
                    redisTemplate.boundHashOps("SeckillGoodsStockCount").increment(seckillOrder.getSeckillId(), 1);
            //队列中从左边加一个数据
            redisTemplate.boundListOps("SeckillGoodsStocKQueue_"+seckillOrder.getSeckillId()).leftPush(goodsId);
        }
        //将用户排队信息删除，排队状态删除
        stringRedisTemplate.delete("SeckillStatus_"+username);
        stringRedisTemplate.delete("UserQueueCount_"+username);
    }

    /***
     * 支付成功修改订单状态
     * @param username
     * @param transactionid
     */
    @Override
    public void updatePayStatus(String username, String transactionid) {
        //获取订单信息
        Object seckillOrder01 = stringRedisTemplate.boundHashOps("SeckillOrder").get(username);
        SeckillOrder seckillOrder = JSONObject.parseObject(seckillOrder01.toString(), SeckillOrder.class);
        //对订单信息进行补充
        //支付创建时间
        seckillOrder.setPayTime(new Date());
        //支付状态
        seckillOrder.setStatus("1");
        //交易流水号
        seckillOrder.setTransactionId(transactionid);
        //将订单信息保存数据库
        seckillOrderMapper.insertSelective(seckillOrder);
        //将redis中的订单数据更新
        stringRedisTemplate.boundHashOps("SeckillOrder").put(username,JSONObject.toJSONString(seckillOrder));
        //将用户排队信息删除，排队状态删除
        stringRedisTemplate.delete("SeckillStatus_"+username);
        stringRedisTemplate.delete("UserQueueCount_"+username);

    }

    /***
     * 秒杀抢单（排队）
     * @param username : 抢单用户
     * @param id : 商品ID
     * @param time : 时间 20200106
     */
    @Override
    public Boolean add(String username, String id, String time) {
        //将用户排队的次数记录redis中，当用户重复排队则对外抛出异常
        Long increment = redisTemplate.boundValueOps("UserQueueCount_" + username).increment(1);
        if (increment>1){
            //重复排队抛异常
            throw  new RuntimeException("已在排队或存在未支付的订单,下单失败");
        }
        SeckillStatus seckillStatus=new SeckillStatus();
        //添加用户名
        seckillStatus.setUsername(username);
        //添加创建时间
        seckillStatus.setCreateTime(new Date());
        //秒杀状态1
        seckillStatus.setStatus(1);
        //秒杀商品id
        seckillStatus.setGoodsId(id);
        //时间段(订单号与应付金额可以先不填充)
        seckillStatus.setTime(time);
        //保存到redis
        String jsonString = JSONObject.toJSONString(seckillStatus);
        stringRedisTemplate.boundValueOps("SeckillStatus_"+username).set(jsonString);
        //将状态发送到MQ,进行异步下单
        rabbitTemplate.convertAndSend("seckillOrderExchange",
                "seckillOrderQueue",jsonString);
        return true;
    }

    /**
     * SeckillOrder条件+分页查询
     * @param seckillOrder 查询条件
     * @param page 页码
     * @param size 页大小
     * @return 分页结果
     */
    @Override
    public PageInfo<SeckillOrder> findPage(SeckillOrder seckillOrder, int page, int size){
        //分页
        PageHelper.startPage(page,size);
        //搜索条件构建
        Example example = createExample(seckillOrder);
        //执行搜索
        return new PageInfo<SeckillOrder>(seckillOrderMapper.selectByExample(example));
    }

    /**
     * SeckillOrder分页查询
     * @param page
     * @param size
     * @return
     */
    @Override
    public PageInfo<SeckillOrder> findPage(int page, int size){
        //静态分页
        PageHelper.startPage(page,size);
        //分页查询
        return new PageInfo<SeckillOrder>(seckillOrderMapper.selectAll());
    }

    /**
     * SeckillOrder条件查询
     * @param seckillOrder
     * @return
     */
    @Override
    public List<SeckillOrder> findList(SeckillOrder seckillOrder){
        //构建查询条件
        Example example = createExample(seckillOrder);
        //根据构建的条件查询数据
        return seckillOrderMapper.selectByExample(example);
    }


    /**
     * SeckillOrder构建查询对象
     * @param seckillOrder
     * @return
     */
    public Example createExample(SeckillOrder seckillOrder){
        Example example=new Example(SeckillOrder.class);
        Example.Criteria criteria = example.createCriteria();
        if(seckillOrder!=null){
            // 主键
            if(!StringUtils.isEmpty(seckillOrder.getId())){
                    criteria.andEqualTo("id",seckillOrder.getId());
            }
            // 秒杀商品ID
            if(!StringUtils.isEmpty(seckillOrder.getSeckillId())){
                    criteria.andEqualTo("seckillId",seckillOrder.getSeckillId());
            }
            // 支付金额
            if(!StringUtils.isEmpty(seckillOrder.getMoney())){
                    criteria.andEqualTo("money",seckillOrder.getMoney());
            }
            // 用户
            if(!StringUtils.isEmpty(seckillOrder.getUserId())){
                    criteria.andEqualTo("userId",seckillOrder.getUserId());
            }
            // 创建时间
            if(!StringUtils.isEmpty(seckillOrder.getCreateTime())){
                    criteria.andEqualTo("createTime",seckillOrder.getCreateTime());
            }
            // 支付时间
            if(!StringUtils.isEmpty(seckillOrder.getPayTime())){
                    criteria.andEqualTo("payTime",seckillOrder.getPayTime());
            }
            // 状态，0未支付，1已支付
            if(!StringUtils.isEmpty(seckillOrder.getStatus())){
                    criteria.andEqualTo("status",seckillOrder.getStatus());
            }
            // 收货人地址
            if(!StringUtils.isEmpty(seckillOrder.getReceiverAddress())){
                    criteria.andEqualTo("receiverAddress",seckillOrder.getReceiverAddress());
            }
            // 收货人电话
            if(!StringUtils.isEmpty(seckillOrder.getReceiverMobile())){
                    criteria.andEqualTo("receiverMobile",seckillOrder.getReceiverMobile());
            }
            // 收货人
            if(!StringUtils.isEmpty(seckillOrder.getReceiver())){
                    criteria.andEqualTo("receiver",seckillOrder.getReceiver());
            }
            // 交易流水
            if(!StringUtils.isEmpty(seckillOrder.getTransactionId())){
                    criteria.andEqualTo("transactionId",seckillOrder.getTransactionId());
            }
        }
        return example;
    }

    /**
     * 删除
     * @param id
     */
    @Override
    public void delete(String id){
        seckillOrderMapper.deleteByPrimaryKey(id);
    }

    /**
     * 修改SeckillOrder
     * @param seckillOrder
     */
    @Override
    public void update(SeckillOrder seckillOrder){
        seckillOrderMapper.updateByPrimaryKey(seckillOrder);
    }

    /**
     * 增加SeckillOrder
     * @param seckillOrder
     */
    @Override
    public void add(SeckillOrder seckillOrder){
        seckillOrderMapper.insert(seckillOrder);
    }

    /**
     * 根据ID查询SeckillOrder
     * @param id
     * @return
     */
    @Override
    public SeckillOrder findById(String id){
        return  seckillOrderMapper.selectByPrimaryKey(id);
    }

    /**
     * 查询SeckillOrder全部数据
     * @return
     */
    @Override
    public List<SeckillOrder> findAll() {
        return seckillOrderMapper.selectAll();
    }
}
